﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using FarseerPhysics.Collision.Shapes;
using FarseerPhysics.Dynamics;
using FarseerPhysics.Dynamics.Contacts;
using FarseerPhysics.Factories;
using FarseerPhysics.SamplesFramework;
using Flatland.Labs;
using Flatland.Utilities;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

/**
* 
* Copyright (c) 2012 Anders Høst Kjærgaard | ahkj@itu.dk
* 
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction, 
* including without limitation the rights to use, copy, modify, merge, publish, distribute, 
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial 
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

namespace Flatland.Elements {
    public class Food {
        private readonly FlatlandWorld _flatland;

        /// <summary>
        /// Texture representing the food.
        /// </summary>
        public Texture2D Texture { get; set; }

        /// <summary>
        /// The Body object of Food
        /// </summary>
        public Body FoodBody { get; set; }

        public string FoodName { get; set; }

        /// <summary>
        /// Main constructor of Food.
        /// </summary>
        /// <param name="flatland"></param>
        /// <param name="position"></param>
        /// <param name="texture"> </param>
        /// <param name="name"> </param>
        public Food(FlatlandWorld flatland, Vector2 position) {
            int c = Utils.Random.Next(5);
            switch (c)
            {
                case 0:
                    Texture = flatland.Content.Load<Texture2D>("med_onlyapple");
                    FoodName = "Apple";
                    break;
                case 1:
                    Texture = flatland.Content.Load<Texture2D>("med_onlygrapes");
                    FoodName = "Grapes";
                    break;
                case 2:
                    Texture = flatland.Content.Load<Texture2D>("med_onlybananas");
                    FoodName = "Bananas";
                    break;
                case 3:
                    Texture = flatland.Content.Load<Texture2D>("med_onlypineapple");
                    FoodName = "Pineapple";
                    break;
                case 4:
                    Texture = flatland.Content.Load<Texture2D>("med_onlypear");
                    FoodName = "Pear";
                    break;
                case 5:
                    Texture = flatland.Content.Load<Texture2D>("med_onlyapple");
                    FoodName = "Apple";
                    break;
            }

            Debug.Assert(Texture != null, "Food texxture not found");
            FoodBody = BodyFactory.CreateBody(flatland.World, position);
            FoodBody.UserData = this;
            PolygonShape ps = new PolygonShape(1f);
            ps.SetAsBox(ConvertUnits.ToSimUnits(Texture.Width / 2), ConvertUnits.ToSimUnits(Texture.Height / 2));
           // Console.WriteLine("Polygon shape: " + ps.Vertices);
            Fixture fixture = FoodBody.CreateFixture(ps);
            FoodBody.OnCollision += FoodCollision;
            FoodBody.CollisionCategories = Category.FOOD_CATEGORY;
            FoodBody.CollidesWith = Category.All;
            FoodBody.Friction = 0f;            
           // Console.WriteLine("food body " + FoodBody.Position);
            _flatland = flatland;
        }

        private bool FoodCollision(Fixture a, Fixture b, Contact contact)
        {

            switch (b.CollisionCategories) {
                case Category.FOOD_CATEGORY:
                    Console.WriteLine("food is seen");
                    break;
            }
            return false;
        }

        public void Draw()
        {
            _flatland.SpriteBatch.Draw(Texture,
                                       ConvertUnits.ToDisplayUnits(FoodBody.Position), null,
                                       Color.White, FoodBody.Rotation,
                                       new Vector2(Texture.Width/2, Texture.Height/2),
                                       1f,
                                       SpriteEffects.None, 0f);
        }

        /// <summary>
        /// Get a list of food items that can randomy placed or placed in a trail.
        /// </summary>
        /// <param name="flatland"></param>
        /// <param name="trail"></param>
        /// <param name="amount"></param>
        /// <param name="indent"></param>
        /// <returns></returns>
        public static List<Food> SetupFood(FlatlandWorld flatland, bool trail, int amount, float centreOffSet = FlatlandLab.BORDERS_DIST_TO_EDGES)
        {
            List<Food> list = new List<Food>(amount);

            //Place food
            int translatedOffset = (int) ConvertUnits.ToDisplayUnits(centreOffSet);
            float x = ConvertUnits.ToSimUnits(Utils.Random.Next(-translatedOffset, translatedOffset));
            float y = ConvertUnits.ToSimUnits(Utils.Random.Next(-translatedOffset, translatedOffset));

            //Random food placement
            if (!trail) {
                for (int j = 0; j < amount; j++) {
                    Food food = new Food(flatland, new Vector2(x, y));
                    list.Add(food);
                    x = ConvertUnits.ToSimUnits(Utils.Random.Next(-translatedOffset, translatedOffset));
                    y = ConvertUnits.ToSimUnits(Utils.Random.Next(-translatedOffset, translatedOffset));
                }
            }

             //Food trail. Not a perfect consstent implementation, but will lay out a resonable food trail for 'not too big' amounts of total food
            else {
                int totalFoodPlaced = 0;
                int xFood = amount / 2;
                //Convert to some point that is at least to the left of the middle
                x = x / 2;
                y = y / 2;
                while (totalFoodPlaced < xFood) {
                    Food food = new Food(flatland, new Vector2(x + (totalFoodPlaced * 20), y));
                    list.Add(food);
                    ++totalFoodPlaced;
                }
                while (totalFoodPlaced < amount) {
                    Food food = new Food(flatland, new Vector2(x, y + ((amount- totalFoodPlaced) * 20)));
                    list.Add(food);
                    ++totalFoodPlaced;
                }
            }
            return list;
        }
    }
}